#include "serial_port.h"
#include <fcntl.h>       // 文件控制定义
#include <unistd.h>      // Unix标准函数定义
#include <dirent.h>      // 目录操作
#include <cstring>       // 字符串操作
#include <iostream>

// 构造函数
serial_port::serial_port() : serial_fd(-1), is_port_opened(false) {}

// 析构函数，关闭串口
serial_port::~serial_port() 
{
    close_port();
}

// 搜索可用的串口设备
std::vector<std::string> serial_port::search_available_ports() 
{
    std::vector<std::string> ports;
    const std::string dev_path = "/dev/";

    DIR* dev_dir = opendir(dev_path.c_str());
    if (!dev_dir) {
        std::cerr << "Unable to open /dev/ directory" << std::endl;
        return ports;
    }

    struct dirent* entry;
    while ((entry = readdir(dev_dir)) != nullptr) {
        std::string name = entry->d_name;
        if (name.find("ttyUSB0") != std::string::npos || name.find("ttyS") != std::string::npos) {
            ports.push_back(dev_path + name);
        }
    }

    closedir(dev_dir);
    return ports;
}

// 打开串口设备
bool serial_port::open_port(const std::string& port_name) 
{
    serial_fd = open(port_name.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
    if (serial_fd == -1) {
        std::cerr << "Error opening serial port: " << port_name << std::endl;
        return false;
    }

    // 设置串口为阻塞模式
    fcntl(serial_fd, F_SETFL, 0);
    is_port_opened = true;
    return true;
}

// 关闭串口设备
void serial_port::close_port() 
{
    if (serial_fd != -1) {
        close(serial_fd);
        serial_fd = -1;
        is_port_opened = false;
    }
}

// 设置串口参数
bool serial_port::configure_port(int baudrate, int databits, int stopbits, char parity, bool hw_ctrl) 
{
    if (!is_port_opened) {
        std::cerr << "Serial port is not open" << std::endl;
        return false;
    }

    memset(&tty, 0, sizeof(tty));

    if (tcgetattr(serial_fd, &tty) != 0) {
        std::cerr << "Error getting terminal attributes" << std::endl;
        return false;
    }

    // 设置波特率
    speed_t baud;
    switch (baudrate) {
        case 9600: baud = B9600; break;
        case 19200: baud = B19200; break;
        case 38400: baud = B38400; break;
        case 115200: baud = B115200; break;
        case 230400: baud = B230400; break;
        case 460800: baud = B460800; break;
        default: std::cerr << "Unsupported baud rate" << std::endl; return false;
    }
    cfsetospeed(&tty, baud);
    cfsetispeed(&tty, baud);

    // 设置数据位
    tty.c_cflag &= static_cast<unsigned int>(~CSIZE); // 清除数据位设置
    switch (databits) {
        case 5: tty.c_cflag |= CS5; break;
        case 6: tty.c_cflag |= CS6; break;
        case 7: tty.c_cflag |= CS7; break;
        case 8: tty.c_cflag |= CS8; break;
        default: std::cerr << "Unsupported data bits" << std::endl; return false;
    }

    // 设置校验位
    switch (parity) {
        case 'N': // 无校验
            tty.c_cflag &= static_cast<unsigned int>(~PARENB);
            break;
        case 'E': // 偶校验
            tty.c_cflag |= PARENB;
            tty.c_cflag &= static_cast<unsigned int>(~PARODD);
            break;
        case 'O': // 奇校验
            tty.c_cflag |= PARENB;
            tty.c_cflag |= PARODD;
            break;
        default:
            std::cerr << "Unsupported parity" << std::endl;
            return false;
    }

    // 设置停止位
    if (stopbits == 2) {
        tty.c_cflag |= CSTOPB;
    } else if (stopbits == 1) {
        tty.c_cflag &= static_cast<unsigned int>(~CSTOPB);
    } else {
        std::cerr << "Unsupported stop bits" << std::endl;
        return false;
    }

    // 硬件流控
    if (hw_ctrl) {
        tty.c_cflag |= CRTSCTS;
    } else {
        tty.c_cflag &= ~CRTSCTS;
    }

    tty.c_cflag |= CLOCAL;  // 忽略调制解调器状态线
    tty.c_cflag |= CREAD;   // 启动接收器

    tty.c_lflag &= static_cast<unsigned int>(~(ICANON | ECHO | ECHOE | ISIG)); // 原始模式
    tty.c_iflag &= static_cast<unsigned int>(~(IXON | IXOFF | IXANY));         // 禁用软件流控
    tty.c_oflag &= static_cast<unsigned int>(~OPOST);                          // 原始输出

    // 将设置生效
    if (tcsetattr(serial_fd, TCSANOW, &tty) != 0) {
        std::cerr << "Error setting terminal attributes" << std::endl;
        return false;
    }

    return true;
}

// 发送字符串数据
int serial_port::send_string_data(const std::string& data) 
{
    if (!is_port_opened) {
        std::cerr << "Serial port is not open" << std::endl;
        return -1;
    }

    int bytes_written = write(serial_fd, data.c_str(), data.size());
    if (bytes_written < 0) {
        std::cerr << "Error writing to serial port" << std::endl;
    }

    return bytes_written;
}

//发送字符数据
int serial_port::send_byte_data(unsigned char *data, int len)
{
    if (!is_port_opened) {
        std::cerr << "Serial port is not open" << std::endl;
        return -1;
    }

    int bytes_written = write(serial_fd, data, len);
    if (bytes_written < 0) {
        std::cerr << "Error writing to serial port" << std::endl;
    }

    return bytes_written;
}

// 接收数据
int serial_port::recv_data_poll(unsigned char *buffer, size_t size) {
    if (!is_port_opened) {
        std::cerr << "Serial port is not open" << std::endl;
        return -1;
    }

    int bytes_read = -1;
    
    if(nullptr != buffer)
    {
        bytes_read = read(serial_fd, buffer, size);

        if (bytes_read < 0) {
            std::cerr << "Error reading from serial port" << std::endl;
            return -1;
        }
    }

    return bytes_read;
}

// 判断串口是否已打开
bool serial_port::is_open() const {
    return is_port_opened;
}
